package com.dycong.common.IOutil;

import com.ibm.icu.text.CharsetDetector;
import com.ibm.icu.text.CharsetMatch;
import lombok.extern.log4j.Log4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import javax.faces.bean.ManagedBean;
import java.io.*;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Random;

import static org.apache.commons.io.FileUtils.readFileToString;

/**
 * Created by Kenti on 2016/3/28.
 * */
@Log4j
@ManagedBean
public class FileUtil {

    private static final String[] FILESIZEEXT=new String[]{"B","KB","MB","GB","TB"};

    public static String getPrettyPrint(Long fileSize){
        int i=0;
        float size=fileSize;
        while (size>=1024){
            size=size/1024;
            i++;
        }
        DecimalFormat df = new DecimalFormat("0.##");
        return df.format(size)+FILESIZEEXT[i];
    }

    /**
     * <p>文件编码互相转换</p>
     * <p>默认转成utf-8 并且会覆盖目标文件</p>
     * @param bytes 原输入is
     * @param destFile 转换后目标文件
     * @return
     */
    public static boolean charsetConvert(byte[] bytes, String destFile){
        Optional<String> charset=charsetDetect(bytes);
        if (charset.isPresent()){
            List<String> lines= null;
            try {
                lines = IOUtils.readLines(new ByteArrayInputStream(bytes),charset.get());
                File file=new File(destFile);
                file.getParentFile().mkdirs();
                FileUtils.writeLines(file,lines);
                return true;
            } catch (IOException e) {
                log.error("error charsetconvert with charset "+charset.get());
            }
        }
        return false;
    }

    /**
     * <p>文件编码互相转换</p>
     * <p>默认转成utf-8 并且会覆盖目标文件</p>
     * @param is 原输入is
     * @param destFile 转换后目标文件
     * @return
     */
    public static boolean charsetConvert(InputStream is, String destFile){
        Optional<String> charset=charsetDetect(is);
        if (charset.isPresent()){
            List<String> lines= null;
            try {
                lines = IOUtils.readLines(is,charset.get());
                File file=new File(destFile);
                file.getParentFile().mkdirs();
                FileUtils.writeLines(file,lines);
                return true;
            } catch (IOException e) {
                log.error("error charsetconvert with charset "+charset.get());
            }
        }
        return false;
    }

    /**
     * <p>文件编码互相转换</p>
     * <p>默认转成utf-8 并且会覆盖目标文件</p>
     * @param orgFile 待转换源文件
     * @param destFile 转换后目标文件
     * @return
     */
    public static boolean charsetConvert(String orgFile,String destFile){
        Optional<String> charset=charsetDetect(orgFile);
        if (charset.isPresent()){
            List<String> lines= null;
            try {
                lines = FileUtils.readLines(new File(orgFile),charset.get());
                FileUtils.writeLines(new File(destFile),lines);
                return true;
            } catch (IOException e) {
                log.error("error charsetconvert with "+orgFile+" charset "+charset.get());
            }
        }
        return false;
    }

    /**
     * 对一个文件进行字符编码的检测
     * @param filePath
     * @return
     */
    public static Optional<String> charsetDetect(String filePath){
        File file=new File(filePath);
        if (file.exists()){
            try {
                return charsetDetect(FileUtils.readFileToByteArray(new File(filePath)));
            } catch (IOException e) {
                log.error("error detect file charset",e);
            }
        }
        return Optional.empty();
    }

    public static Optional<String> charsetDetect(InputStream is){
        CharsetDetector charsetDetector=new CharsetDetector();
        try {
            charsetDetector.setText(is);
            CharsetMatch[] matches=charsetDetector.detectAll();
            if (matches!=null && matches.length>0)
                return Optional.of(matches[0].getName());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Optional.empty();
    }

    /**
     * 对一个文件进行字符编码的检测
     * @param bytes 字节
     * @return
     */
    public static Optional<String> charsetDetect(byte[] bytes){
        return charsetDetect(new ByteArrayInputStream(bytes));
    }

    public static String genFileName(String originFilename) {
        int index=originFilename.lastIndexOf(".");
        String suffix ="";
        if (index>=0){
            suffix=originFilename.substring(index);
        }

        String fileName = getImageId() + suffix;
        return fileName;
    }


    public static String getImageId(){
        Date data=new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String timestr = simpleDateFormat.format(data);
        Integer rand = (int)(Math.random()*9000+1000);
        return timestr+rand;
    }

    static final Long FILE_COPY_BUFFER_MAX_SIZE=1024*1024*30L;

   //todo copyFrom: package org.apache.commons.com.dycong.common.IO.socket.FileUtils--->复制文件最高效的方法  com.dycong.common.IO.nio
    private static void doCopyFile(final File srcFile, final File destFile, final boolean preserveFileDate)
            throws IOException {
        if (destFile.exists() && destFile.isDirectory()) {
            throw new IOException("Destination '" + destFile + "' exists but is a directory");
        }

        FileInputStream fis = null;
        FileOutputStream fos = null;
        FileChannel input = null;
        FileChannel output = null;
        try {
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);
            input = fis.getChannel();
            output = fos.getChannel();
            final long size = input.size(); // TODO See com.dycong.common.IO-386
            long pos = 0;
            long count = 0;
            while (pos < size) {
                final long remain = size - pos;
                count = remain > FILE_COPY_BUFFER_MAX_SIZE ? FILE_COPY_BUFFER_MAX_SIZE : remain;
                final long bytesCopied = output.transferFrom(input, pos, count);
                if (bytesCopied == 0) { // com.dycong.common.IO-385 - can happen if file is truncated after caching the size
                    break; // ensure we don't loop forever
                }
                pos += bytesCopied;
            }
        } finally {
            org.apache.commons.io.IOUtils.closeQuietly(output, fos, input, fis);
        }

        final long srcLen = srcFile.length(); // TODO See com.dycong.common.IO-386
        final long dstLen = destFile.length(); // TODO See com.dycong.common.IO-386
        if (srcLen != dstLen) {
            throw new IOException("Failed to copy full contents from '" +
                    srcFile + "' to '" + destFile + "' Expected length: " + srcLen + " Actual: " + dstLen);
        }
        if (preserveFileDate) {
            destFile.setLastModified(srcFile.lastModified());
        }
    }


    public static void main(String[] args)throws Exception {
        FileUtil fileUtil=new FileUtil();
        for (int i=0;i<4;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    long xx=Math.abs((long)new Random().nextInt());
                    System.out.println(xx+" "+fileUtil.getPrettyPrint(xx));
                }
            }).start();
        }
//        charsetConvert(new FileInputStream("E:\\软件\\迅雷下载\\[阳光电影www.ygdy8.com].三少爷的剑.HD.720p.国语中字.mkv"),"E:\\软件\\迅雷下载\\[阳光电影www.ygdy8.com].三少爷的剑.HD.720p.国语中字.mkv");
        System.out.println(readFileToString(new File("E:\\data.txt"),"utf-8"));
    }

}